# python modules
import sys, os
from xml.sax import make_parser

# QT4 modules
from PyQt4 import QtCore, QtGui, uic

# Load UI from auto-mate.ui
(AutoMateForm, AutoMateBase) = uic.loadUiType(os.path.join(os.path.dirname(__file__), "auto-mate.ui"))

#Internal modules:
from installer import Installer
from apptreemodel import AppsModel
from tweakmodel import TweaksModel
from inputparsers import *
from application import Application, AppException
from tweak import Tweak

class AutoMateGui(AutoMateBase):
	"""Main window gui."""

	def __init__(self, db_root="database", parent=None):
		'''initializes the gui class.

		@param db_root database root directory
		@param paren parent window'''

		AutoMateBase.__init__(self, parent)
		AutoMateForm().setupUi(self)

		self.db_root = db_root

		self.appModel = AppsModel(getApps(self.db_root))
		self.apps_view = self.findChild(QtGui.QTreeView, "apps_view")
		self.apps_view.setModel(self.appModel)

		self.tweakModel = TweaksModel(getTweaks(self.db_root))
		self.tweaks_view = self.findChild(QtGui.QListView, "tweaks_view")
		self.tweaks_view.setModel(self.tweakModel)

		self.setupActions()

		self.button_install = self.findChild(QtGui.QPushButton, "button_install")
		self.connect(self.button_install,QtCore.SIGNAL("clicked()"), self.install)
		self.button_clear = self.findChild(QtGui.QPushButton, "button_clear")
		self.connect(self.button_clear,QtCore.SIGNAL("clicked()"), self.clearApps)

		self.button_tweak = self.findChild(QtGui.QPushButton, "button_tweak")
		self.connect(self.button_tweak,QtCore.SIGNAL("clicked()"), self.tweak)
		self.button_clear_reg = self.findChild(QtGui.QPushButton, "button_clear_reg")
		self.connect(self.button_clear_reg,QtCore.SIGNAL("clicked()"), self.clearTweaks)

		self.installer = Installer(self.statusBar())


	def setupActions(self):
		'''binds actions to slots.'''

		self.actionClose = self.findChild(QtGui.QAction, "actionClose")
		self.connect(self.actionClose, QtCore.SIGNAL("triggered(bool)"), self.quit)
		self.actionInstall = self.findChild(QtGui.QAction, "actionInstall")
		self.connect(self.actionInstall, QtCore.SIGNAL("triggered(bool)"), self.install)
		self.actionAbout = self.findChild(QtGui.QAction, "actionAbout")
		self.connect(self.actionAbout, QtCore.SIGNAL("triggered(bool)"), self.about)
		self.actionImport = self.findChild(QtGui.QAction, "actionImport")
		self.connect(self.actionImport, QtCore.SIGNAL("triggered(bool)"), self.importSel)
		self.actionExport = self.findChild(QtGui.QAction, "actionExport")
		self.connect(self.actionExport, QtCore.SIGNAL("triggered(bool)"), self.exportSel)
		self.actionTweak = self.findChild(QtGui.QAction, "actionTweak")
		self.connect(self.actionTweak, QtCore.SIGNAL("triggered(bool)"), self.tweak)


	def install(self):
		'''installs selection of the tree view.'''
		apps = self.appModel.getInstallList()
		for app in apps:
			self.installer.install(app)
		self.appModel.clearChecks()
		self.appViewBlink()

	def tweak(self):
		'''runs the selected tweaks'''
		tweaks = self.tweakModel.getTweakList()
		for tweak in tweaks:
			self.installer.tweak(tweak)
		self.tweakModel.clearChecks()
		self.tweakViewBlink()

	def quit(self):
		'''exits program.'''

		sys.exit(0)

	def about(self):
		'''pops a simple about dialog'''

		QtGui.QMessageBox.about(self,self.tr("About Auto-Mate"),self.tr("""<center><b>Auto-Mate</b></center>\nHelps automate installing applications on windows and performing other actions.
A GUI front-end to a database of applications and actions for windows."""));

	def importSel(self):
		'''imports selection from a template file, by using a file-dialog.'''

		filename = str(QtGui.QFileDialog.getOpenFileName(self,"Select a template file..",QtCore.QString(),self.tr("Template files (*.xml)")))
		if not filename:
			self.statusBar().showMessage("Loading aborted.", 3000)
			return
		filename = os.path.split(filename)[-1]
		parser = make_parser()
		handler = TempHandler()
		parser.setContentHandler(handler)
		parser.parse(open(filename))
		apps = [ ]
		tweaks = [ ]
		for (app_name, version) in handler.toInstall:
			try:
				if version:
					app = Application(app_name, self.db_root)
					ver_names = [ver.version for ver in app.versions]
					if version in ver_names:
						apps.append(app.versions[ver_names.index(version)])
				else:
					apps.append(Application(app_name, self.db_root).last_version())
			except AppException:
				pass
		for tweak in handler.toTweak:
			tweak_names = [t.name for t in getTweaks(self.db_root)]
			if tweak in tweak_names:
				tweaks.append(getTweaks(self.db_root)[tweak_names.index(tweak)])
		self.tweakModel.setTweakList(tweaks)
		self.tweakViewBlink()
		self.appModel.setInstallList(apps)
		self.appViewBlink()
		self.statusBar().showMessage("Selection successfully loaded.", 3000)


	def exportSel(self):
		'''exports selection into template file, by using a file-dialog..'''

		filename = QtGui.QFileDialog.getSaveFileName(self,"Select desination for exporting..",QtCore.QString(),self.tr("Template files (*.xml)"))
		if not filename:
			self.statusBar().showMessage("Saving aborted.", 3000)
			return
		fsock = QtCore.QFile(filename)
		xmlString = "<?xml version='1.0' encoding='utf-8'?>\n<template>\n"
		for ver in self.appModel.getInstallList():
			app = self.getVerApp(ver)
			verString = ""
			if not app.last_version() == ver:
				verString = " version=\""+ver.version+"\" "
			xmlString += "\t<install"+verString+">" + ver.name + "</install>\n"
		for tweak in self.tweakModel.getTweakList():
			xmlString += "\t<tweak>" + tweak.name + "</tweak>\n"
		xmlString += "</template>"
		if(fsock.open(QtCore.QIODevice.Text | QtCore.QIODevice.WriteOnly)):
			fsock.writeData(xmlString)
		fsock.close()
		self.statusBar().showMessage("Selection successfully saved.", 3000)


	def clearApps(self):
		'''cleares the tree view off checks.'''

		self.appModel.clearChecks()
		self.appViewBlink()
		self.statusBar().showMessage("Selection Cleared.", 3000)

	def clearTweaks(self):
		'''cleares the tweaks view.'''

		self.tweakModel.clearChecks()
		self.tweakViewBlink()
		self.statusBar().showMessage("Selection Cleared.", 3000)


	def appViewBlink(self):
		'''blinks table to allow redrawing.'''

		self.apps_view.hide()
		self.apps_view.show()

	def tweakViewBlink(self):
		'''blinks table to allow redrawing.'''

		self.tweaks_view.hide()
		self.tweaks_view.show()


	def getVerApp(self, version):
		'''Returns Application object for given version.

		@param version version of returned application'''

		path = os.path.split(version.ver_path)[0]
		pathApp = os.path.split(path)[1]
		return Application(pathApp ,self.db_root)



def getApps(folder):
	'''Load applications from database'''

	apps = [ ]
	for fol in os.listdir(folder):
		if os.path.isdir(os.path.join(folder, fol)):
			try:
				apps.append(Application(fol, folder))
			except AppException:
				pass
	return apps

def getTweaks(folder):
	parser = make_parser()
	handler = TweakHandler()
	parser.setContentHandler(handler)
	parser.parse(open(os.path.join(folder, 'tweaks', 'index.xml')))
	tweaks = [ ]
	for (tweak, desc) in handler.tweaks:
		tweaks.append(Tweak(os.path.join(folder,'tweaks',tweak),desc))
	return tweaks
